import {
  Body,
  Controller,
  Get,
  Post,
  Query,
  UploadedFiles,
  UseInterceptors,
} from '@nestjs/common';
import { AppService } from './app.service';
import { FilesInterceptor } from '@nestjs/platform-express';
import * as Multer from 'multer';
import express from 'express';
import * as fs from 'fs';
import * as path from 'path';

const dirPath = path.join(process.cwd() + '/uploads');

const storage = Multer.diskStorage({
  destination(
    req: express.Request,
    file: Express.Multer.File,
    callback: (error: Error | null, filename: string) => void,
  ) {
    if (!fs.existsSync(dirPath)) {
      fs.mkdirSync(dirPath);
    }
    callback(null, dirPath);
  },
});

@Controller()
export class AppController {
  constructor(private readonly appService: AppService) {}

  @Post('upload')
  @UseInterceptors(
    FilesInterceptor('files', 2, {
      storage: storage,
    }),
  )
  uploadFile(
    @UploadedFiles() files: Array<Express.Multer.File>,
    @Body() params: { name: string },
  ): boolean {
    const file = files[0];
    const filename = params.name.match(/(.+)\_\d+$/)[1];
    const fileNamePath = dirPath + '/chunk_' + filename;
    if (!fs.existsSync(fileNamePath)) {
      fs.mkdirSync(fileNamePath);
    }
    fs.cpSync(file.path, `${fileNamePath}/${params.name}`);
    fs.rmSync(file.path);
    return true;
  }
  @Get('merge')
  mergeFile(@Query() params: { name: string }) {
    const chunkPath = 'uploads/chunk_' + params.name
    const fileList = fs.readdirSync(chunkPath);
    const getIndex = (str) =>
      parseInt(str.match(/\_\d+$/)[0].replace('_', ''), 10);
    const sortedList = fileList.sort((prev, next) => {
      return getIndex(prev) - getIndex(next);
    });

    let count = 0;
    let startPos = 0;
    sortedList.forEach((file) => {
      const filePath = `${chunkPath}/${file}`;
      const stream = fs.createReadStream(filePath);

      stream
        .pipe(
          fs.createWriteStream('uploads/' + params.name, {
            start: startPos,
          }),
        )
        .on('finish', () => {
          count++;

          if (count === sortedList.length) {
            fs.rm(
              chunkPath,
              {
                recursive: true,
              },
              () => {},
            );
          }
        });

      startPos += fs.statSync(filePath).size;
    });

    return true;
  }
}
